﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using AudioPlayer.Database;
using System.ComponentModel;
using AudioPlayer.Plugin;
using AudioPlayer.Plugin.Storage;
namespace AudioPlayer.GUI.List {
	internal class ListControl : Control {
		#region Variables
		#region Style
		private Font _headerFont;
		private Font _itemFont;
		private Color _headerFontColor;

		private Color _headerBackNormal1;
		private Color _headerBackNormal2;

		private Color _headerBackHover1;
		private Color _headerBackHover2;
			
		private Color _headerBorder;

		private Color _itemBorderSelect;
		private Color _itemBorderHover;
		private Color _itemBackSelect1;
		private Color _itemBackSelect2;

		private Color _itemBackHover1;
		private Color _itemBackHover2;
		private LinearGradientBrush _itemBackBrush;


		private Color _helpColorBorder;
		private Color _helpBack1;
		private Color _helpBack2;

		private Color _itemFontColorNormal;
		private Color _itemFontColorSelect;
		#endregion
		private HeaderCollection _headers;
		private ListCollection _items;
		private Point _mouseDown;
		private ListDrag _dragProvider;

		private bool _showHover = false;

		private delegate void InvLibraryScan(object sender, EventArgs e);
		#endregion
		#region Constructor
		public ListControl() {
			if (!this.DesignMode) {
				Init();
				InitStyle();
				InitTemp();
				this.MinimumSize = new Size(200, 40);
				this.BackColor = Color.White;
				this.ResizeRedraw = true;
				this.DoubleBuffered = true;
				this.AllowDrop = true;
				this.Library_Update(this, EventArgs.Empty);
				InitPlugin();
			}
		}	
		#endregion
		#region Private Voids
		/// <summary>
		/// Inits this instance.
		/// </summary>
		private void Init() {
			_headers = new HeaderCollection();
			_headers.Add(new Header("Nr",HeaderType.Nr,20));
			_headers.Add(new Header("Track",HeaderType.Track,true));
			_headers.Add(new Header("Time",HeaderType.Time,40));
			_headers.Add(new Header("Rating",HeaderType.Rating,90));

			this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
		}
		/// <summary>
		/// Inits the style.
		/// </summary>
		private void InitStyle() {
			_itemFont = new Font("Verdana", 8);
			_headerFont = new Font("Verdana", 8);
			_headerFontColor = Color.DarkGray;
			_headerBackNormal1 = Color.FromArgb(242, 242, 242);
			_headerBackNormal2 = Color.FromArgb(255, 255, 255);

			_headerBackHover1 = Color.FromArgb(222, 222, 222);
			_headerBackHover2 = Color.FromArgb(245, 245, 245);
			_headerBorder = Color.FromArgb(209, 214, 221);

			_itemBorderSelect = Color.FromArgb(80, 117, 167);
			_itemBorderHover = ControlPaint.LightLight(_itemBorderSelect);
			_itemBackSelect1 = Color.FromArgb(180, 204, 235);
			_itemBackSelect2 = Color.FromArgb(151, 189, 236);

			_itemBackHover1 = ControlPaint.LightLight(_itemBackSelect1);
			_itemBackHover2 = ControlPaint.LightLight(_itemBackSelect2);

			_itemFontColorNormal = Color.DarkGray;
			_itemFontColorSelect = Color.White;
			

			_helpColorBorder = Color.FromArgb(80, 117, 167);
			_helpBack1 = Color.FromArgb(180, 204, 235);
			_helpBack2 = Color.FromArgb(131, 169, 216);


		}
		/// <summary>
		/// Inits the temp.
		/// </summary>
		private void InitTemp() {
			if (!this.DesignMode) {
				Config.Library.Update += new EventHandler(Library_Update);
			}
		}
		/// <summary>
		/// Inits the plugin.
		/// </summary>
		private void InitPlugin() {
			if (Config.Plugins.HasPlayControl) {
				Config.Plugins.PlayControl.Starting += new EventHandler(PlayControl_Starting);
			} else {
				//Config.Plugins.PluginLoad += new Action<AudioPlayer.Plugin.IPluginBase>(InitPlugin);
			}
		}	
		/// <summary>
		/// Inits the plugin.
		/// </summary>
		/// <param name="obj">The obj.</param>
		private void InitPlugin(IPlugin obj) {
			InitPlugin();
		}
		private void DrawBuffered(Graphics g) {
			if (this.Created && this.Width > 0) {
				Bitmap bmp = new Bitmap(this.Width, this.Height);
				Graphics dbl = Graphics.FromImage(bmp);
				this.Draw(dbl);

				g.DrawImage(bmp, 0, 0);

				//Cleanup
				dbl.Dispose();
				bmp.Dispose();
			}
		}
		/// <summary>
		/// Draws everyting
		/// </summary>
		/// <param name="g">The Graphics.</param>
		private void Draw(Graphics g) {
			
			DrawHeader(g);
			DrawItem(g);
			if (this.Items.Count == 0) {
				//DrawHelp(g);
			}
		}
		/// <summary>
		/// Draws all Headers
		/// </summary>
		/// <param name="g">The Graphics.</param>
		private void DrawHeader(Graphics g){
			for (int i = 0; i < this.Headers.Count; i++) {
				DrawHeader(g, this.Headers[i]);
			}
		}
		/// <summary>
		/// Draws Header.
		/// </summary>
		/// <param name="g">The graphics.</param>
		/// <param name="h">The header.</param>
		private void DrawHeader(Graphics g, Header h) {
			//g.FillRectangle(Brushes.White, h.Bounds);
			LinearGradientBrush brush = null;
			if (!h.Hover) {
				brush = new LinearGradientBrush(h.Bounds, _headerBackNormal1, _headerBackNormal2, LinearGradientMode.Vertical);
			} else {
				brush = new LinearGradientBrush(h.Bounds, _headerBackHover1, _headerBackHover2, LinearGradientMode.Vertical);
			}
			g.FillRectangle(brush, h.Bounds);
			g.DrawLine(new Pen(_headerBorder, 1), h.Bounds.X + h.Bounds.Width - 1, 2, h.Bounds.X + h.Bounds.Width - 1, h.Bounds.Height - 4);
			g.DrawString(h.Text, _headerFont, new SolidBrush(_headerFontColor), new Point(h.Bounds.X + 3, h.Bounds.Y + 4));
			g.DrawLine(new Pen(_headerBorder, 1), h.Bounds.Left, h.Bounds.Bottom-1, h.Bounds.Right, h.Bounds.Bottom-1);
		}
		/// <summary>
		/// Draws all Items
		/// </summary>
		/// <param name="g">The Graphics.</param>
		private void DrawItem(Graphics g) {
			if (this.Items.HasItems) {
				//g.FillRectangle(Brushes.White, new Rectangle(0, 20, this.Width, this.Height));
				for (int i = this.Items.First; i < this.Items.End; i++) {
					if (i < this.Items.Count) {
						DrawItem(g, this.Items[i]);
					}
				}
			}
		}
		/// <summary>
		/// Draws Items list.
		/// </summary>
		/// <param name="g">The Graphics.</param>
		/// <param name="list">The list.</param>
		private void DrawItem(Graphics g, IList<ListItem> list) {
			foreach (ListItem item in list) {
				this.DrawItem(g, item);
			}
		}
		/// <summary>
		/// Draws Items.
		/// </summary>
		/// <param name="g">The Graphics.</param>
		/// <param name="item">The item.</param>
		private void DrawItem(Graphics g, ListItem item) {
			if (item.Visible) {
				DrawItemBack(g, item);
				foreach (Header h in this.Headers) {
					DrawItem(g, item, h);
				}
				DrawItemBorder(g, item);
				item.Checked = true;
			}
		}
		/// <summary>
		/// Draws Item of specified header.
		/// </summary>
		/// <param name="g">The Graphics.</param>
		/// <param name="item">The Item.</param>
		/// <param name="h">The header.</param>
		private void DrawItem(Graphics g, ListItem item,Header h) {
			g.SmoothingMode = SmoothingMode.HighQuality;
			Rectangle rectFull = new Rectangle(h.Bounds.X, item.Bounds.Y, h.Bounds.Width, item.Bounds.Height);
			Rectangle rectText = new Rectangle(h.Bounds.X + 2, item.Bounds.Y + 3, h.Bounds.Width - 2, item.Bounds.Height - 6);
			Color c = Color.Empty;
			if (item.Selected || item.Hover) {
				c = _itemFontColorSelect;
			} else {
				c = _itemFontColorNormal;
			}
			StringFormat format = new StringFormat();
			format.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
			format.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide;
			format.LineAlignment = StringAlignment.Far;
			format.Trimming = StringTrimming.None;
			
			switch (h.Type) {
				case HeaderType.Nr:
					g.DrawString(item.Index.ToString(), _itemFont, new SolidBrush(c), rectText,format);
					if (!item.Checked) {
						h.Maximum = TextRenderer.MeasureText(item.Index.ToString(), _headerFont).Width;
					}
					
					break;
				case HeaderType.Track:
					g.DrawString(item.Song.Title, _itemFont, new SolidBrush(c), rectText, format);
					if (!item.Checked) {
						h.Maximum = TextRenderer.MeasureText(item.Song.Title, _headerFont).Width;
					}
					break;
				case HeaderType.Time:
					g.DrawString(item.Song.Length.ToString(), _itemFont, new SolidBrush(c), rectText, format);
					if (!item.Checked) {
						h.Maximum = TextRenderer.MeasureText(item.Song.Length.ToString(), _headerFont).Width;
					}
					break;
				case HeaderType.Rating:
					if (!item.Checked) {
						h.Maximum = 90;
					}
					int starX = rectFull.X;
					for(int starC = 1;starC<=5;starC++){
						if (item.Song.Rating >= starC) {
							//g.DrawImage(Config.Images.StarFull, starX, rect.Y+2);
						} else {
							//g.DrawImage(Config.Images.StarBlank, starX, rect.Y+2);
						}
						starX += 18;
					}
					break;
			}
			g.SmoothingMode = SmoothingMode.Default;
		}
		/// <summary>
		/// Draws Item border.
		/// </summary>
		/// <param name="g">The Graphics.</param>
		/// <param name="item">The Item.</param>
		private void DrawItemBorder(Graphics g, ListItem item) {
			g.SmoothingMode = SmoothingMode.HighQuality;
			if (item.Selected || item.Hover) {
				Pen pBorder = null;
				if (item.Selected) {
					pBorder = new Pen(_itemBorderSelect);
				} else if (item.Hover) {
					pBorder = new Pen(_itemBorderHover);
				}
				if (item.Prev == null || (!item.Prev.Selected)) {
					//Draw top border, only if previous items is not selected.
					g.DrawLine(pBorder, item.Bounds.Left, item.Bounds.Top, item.Bounds.Right, item.Bounds.Top);
				}
				if (item.Next == null || (!item.Next.Selected)) {
					g.DrawLine(pBorder, item.Bounds.Left, item.Bounds.Bottom - 1, item.Bounds.Right, item.Bounds.Bottom - 1);
				}
			}
			g.SmoothingMode = SmoothingMode.Default;
		}
		/// <summary>
		/// Draws Item background.
		/// </summary>
		/// <param name="g">The Graphics.</param>
		/// <param name="item">The Item.</param>
		private void DrawItemBack(Graphics g, ListItem item) {
			if (item.Even) {
				g.FillRectangle(new SolidBrush(ControlPaint.LightLight(ControlPaint.LightLight(_itemBackHover1))), item.Bounds);
			} else {
				g.FillRectangle(Brushes.White, item.Bounds);
			}
			
			if ((item.Selected || item.Hover) && (item.Bounds != Rectangle.Empty)) {
				if (item.Selected) {
					_itemBackBrush = new LinearGradientBrush(item.Bounds, _itemBackSelect2, _itemBackSelect1, LinearGradientMode.Vertical);
				} else if (item.Hover) {
					_itemBackBrush = new LinearGradientBrush(item.Bounds, _itemBackHover2, _itemBackHover1, LinearGradientMode.Vertical);
				}
				g.FillRectangle(_itemBackBrush, item.Bounds);
			}
		}
		/// <summary>
		/// Draws Select items list to bitmap.
		/// </summary>
		/// <returns></returns>
		private Bitmap DrawDragBack() {
			List<ListItem> list = (List<ListItem>)this.Items.SelectedItems;
			List<ListItem> visb = new List<ListItem>();
			//ListItem temp = null;
			int h = 0;
			int count = 0;
			if (list.Count > 4) {
				h = 4 * 20;
				count = 4;


				//Song tempSong = new Song();
				//tempSong.Title = string.Format("    Plus {0} items more.", (list.Count - 3));
				//temp = new ListItem(tempSong);
				//temp.Selected = true;
				for (int i = 0; i < count; i++) {
					visb.Add(list[i]);
				}
				//visb.Add(temp);
			} else {
				h = list.Count * 20;
				count = list.Count;
				visb = list;
			}
			this.Items.SetSlideSelect(visb);

			Bitmap bmp = new Bitmap(this.Headers[1].Width, h);
			Graphics g = Graphics.FromImage(bmp);
			for (int i = 0; i < visb.Count; i++) {
				Rectangle orgRect = visb[i].Bounds;
				visb[i].Bounds = new Rectangle(0, i * 20, bmp.Width, 20);

				DrawItemBack(g,visb[i]);
				DrawItem(g, visb[i], this.Headers[1]);
				DrawItemBorder(g,visb[i]);
				visb[i].Bounds = orgRect;
			}
			g.Dispose();
			this.Items.SetSlideDefault(list);
			return bmp;
		}
		/// <summary>
		/// Clicks Items
		/// </summary>
		/// <param name="item">The item.</param>
		private void ItemClick(ListItem item) {
			this.ItemClick(item, true);
		}
		private void ItemClick(ListItem item, bool play) {
			Graphics g = this.CreateGraphics();

			if (ModifierKeys == Keys.Control) {
				#region Selection
				if (item.Selected) {
					item.Selected = false;
					this.Items.SelectedItems.Remove(item);
				} else {
					item.Selected = true;
					this.Items.SelectedItems.Add(item);
				}
				this.DrawItem(g, item);
				foreach (ListItem itm in this.Items.SelectedItems) {
					this.DrawItem(g, itm);
				}
				#endregion
			} else {
				#region Listen
				this.Items.SelectNone();
				if (this.Items.SelectedCount > 0) {
					for (int i = 0; i < this.Items.SelectedItems.Count; i++) {
						if (this.Items.SelectedItems[i] != item) {
							this.DrawItem(g, this.Items.SelectedItems[i]);
						}
					}
				}
				this.Items.SelectedItems.Clear();
				item.Selected = true;
				this.Items.SelectedItems.Add(item);

				if (play) {
					try {
						if (Config.Plugins.HasPlayControl) {
							Config.Plugins.PlayControl.Play(item.Song);
						}
					} catch {
						//Show what's wrong?
					}
				}
				//Draw selected item
				this.DrawItem(g, item);
				#endregion
			}
			g.Dispose();
		}
		/// <summary>
		/// Handles mouse move event.
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
		private void MouseMoving(MouseEventArgs e) {
			#region Header Stuff
			Header h = _headers.HitInfo(e.Location);

			if (h != null) {
				//Mouse'as yra virs headerio
				Graphics g = this.CreateGraphics();
				Header hover = _headers.Hover;
				if (hover != null && h != hover) {
					hover.Hover = false;
					hover.Drawed = false;
					DrawHeader(g, hover);
				}
				h.Hover = true;
				if (h.Drawed == false) {
					DrawHeader(g, h);
					h.Drawed = true;
				}
				if (h.ShowResize(e.Location)) {
					this.Cursor = Cursors.SizeWE;
				} else {
					this.Cursor = Cursors.Default;
				}
			} else {
				Header hover = _headers.Hover;
				if (hover != null) {
					hover.Hover = false;
					hover.Drawed = false;
					DrawHeader(this.CreateGraphics(), hover);
				} else {
					_headers.UnHover();
					_headers.UnDrawed();
				}
				if (Cursor != Cursors.Default) {
					Cursor = Cursors.Default;
				}
			}
			#endregion

			#region Items Stuff
			if (e.Button == MouseButtons.None && this.ShowHover) {
				ListItem item = this.Items.HitInfo(e.Location);
				//Make sure it's not null, it's not selected or hover
				if (item != null && !item.Hover && !item.Selected) {
					Graphics g = this.CreateGraphics();
					if (this.Items.Hover != null) {
						//Let's unhover current item
						this.Items.Hover.Hover = false;
						this.DrawItem(g, this.Items.GetNeighbours(this.Items.Hover));
					}
					item.Hover = true;
					this.Items.Hover = item;
					this.DrawItem(g, this.Items.GetNeighbours(item));
				} else {
					if (this.Items.Hover != null && item != null && item.Selected) {
						this.Items.Hover.Hover = false;
						this.DrawItem(this.CreateGraphics(), this.Items.GetNeighbours(this.Items.Hover));
						this.Items.Hover = null;
					}
				}
			}
			#endregion
		}
		/// <summary>
		/// Checks if user is draging, and if is, when start custom drag.
		/// </summary>
		private void DoDrag() {
			if (_mouseDown != null && _mouseDown != Point.Empty && this.Items.SelectedItems.Count > 0) {
				Point mPoint = this.PointToClient(MousePosition);
				int distX = Math.Abs(mPoint.X - _mouseDown.X);
				int distY = Math.Abs(mPoint.Y - _mouseDown.Y);

				if (distX > 15 || distY > 15) {
					Bitmap bmp = this.DrawDragBack();
					if (_dragProvider == null) {
						_dragProvider = new ListDrag(bmp, this.Items.SelectedItems);
						_dragProvider.Close += new EventHandler(DragProvider_Close);
						_dragProvider.Location = MousePosition;
						_dragProvider.Show(this.FindForm());
					}
				}
			}
		}

		private void SelectPrev() {
			if (this.Items.SelectedCount > 0 && this.Items.SelectedFirst.Index > 0) {
				ListItem item = this.Items.SelectedFirst;
				this.ClearSelection();

				if (item.Prev != null) {
					item.Prev.Selected = true;

					Graphics g = this.CreateGraphics();
					this.DrawItem(g, item.Prev);
					g.Dispose();

					this.Items.SelectedFirst = item.Prev;
				}
			}
		}
		private void SelectNext() {
			if (this.Items.SelectedCount > 0 && (this.Items.SelectedFirst.Index<this.Items.Count-1)) {
				ListItem item = this.Items.SelectedFirst;
				this.ClearSelection();

				if (item.Next != null) {
					item.Next.Selected = true;

					Graphics g = this.CreateGraphics();
					this.DrawItem(g, item.Next);
					g.Dispose();

					this.Items.SelectedFirst = item.Next;
				}
			}	
		}
		private void ClearSelection() {
			if (this.Items.HasItems) {
				IList<ListItem> selection = this.Items.SelectedItems;
				if (selection != null && selection.Count > 0) {
					this.Items.SelectNone();
				}
				Graphics g = this.CreateGraphics();
				foreach (ListItem item in selection) {
					this.DrawItem(g, item);
				}
				g.Dispose();
			}
		}
		#endregion		
		#region Public Voids
		/// <summary>
		/// Handles mouse wheel event.
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
		public new void MouseWheel(MouseEventArgs e) {
			bool redraw = false;
			if (e.Delta < 0) {
				if (this.Items.CanScrollDown) {
					this.Items.ScrollDown();
					redraw = true;
				}
			} else {
				if (this.Items.CanScrollUp) {
					this.Items.ScrollUp();
					redraw = true;
				}
			}
			if (redraw) {
				this.DrawItem(this.CreateGraphics());
			}
		}

		/// <summary>
		/// Handles drag events
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
        public void DragDropEnter(DragEventArgs e){
			object data = e.Data.GetData(DataFormats.FileDrop);
			if (data != null) {
				if(data is String[]){
					String[] list = (String[])data;
					if (list != null && list.Length > 0) {
						e.Effect = DragDropEffects.All;
						Console.WriteLine("YEY!");
					}
				}
			}
        }
		/// <summary>
		/// Handles drag events
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
		public void DragDropOver(DragEventArgs e) {
			object data = e.Data.GetData(DataFormats.FileDrop);
			if (data != null) {
				if (data is String[]) {
					String[] list = (String[])data;
					if (list != null && list.Length > 0) {
						e.Effect = DragDropEffects.All;
					}
				}
			}
		}
		/// <summary>
		/// Handles drag events
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
		public void DragDropDone(DragEventArgs e) {
			object data = e.Data.GetData(DataFormats.FileDrop);
			if (data != null) {
				if (data is String[]) {
					String[] list = (String[])data;
					if (list != null && list.Length > 0) {
						Config.Library.Scan(list);
						
					}
				}
			}
		}

		/// <summary>
		/// Finds the specified item, by it's song.
		/// </summary>
		/// <param name="song">The Song.</param>
		/// <returns>Item, or null</returns>
		public ListItem Find(ISong song) {
			foreach (ListItem item in this.Items) {
				if (item.Song == song) {
					return item;
				}
			}
			return null;
		}
		#endregion
		#region Override
		protected override void OnPaint(PaintEventArgs e) {
			if (!this.DesignMode) {
				this.DrawBuffered(e.Graphics);
			}
		}
		protected override void OnResize(EventArgs e) {
			base.OnResize(e);
			if (this.Created && !this.DesignMode) {
				this.Headers.MaxWidth = this.Width;
				this.Items.Height = this.Height;
				this.Items.Width = this.Width;
				this.Items.Rebound();
				this.Headers.Resize();
				this.DrawItem(this.CreateGraphics());
			}
		}
		
		protected override void OnMouseDown(MouseEventArgs e) {
			#region Header Stuff
			
			#endregion		

			if (e.Button == MouseButtons.Left) {
				_mouseDown = e.Location;
			} else {
				_mouseDown = Point.Empty;
			}
			ListItem itm = this.Items.HitInfo(e.Location);
			if (itm != null) {
				ItemClick(itm, false);
			}
			this.Select();
			base.OnMouseDown(e);
		}
		
		protected override void OnMouseUp(MouseEventArgs e) {
			#region Header Stuff
			
			#endregion
			_mouseDown = Point.Empty;
			
			this.Select();
			base.OnMouseUp(e);
		}
		protected override void OnMouseDoubleClick(MouseEventArgs e) {
			_mouseDown = Point.Empty;
			ListItem itm = this.Items.HitInfo(e.Location);
			if (itm != null) {
				ItemClick(itm);
			}
			this.Select();
			base.OnMouseDoubleClick(e);
		}
		protected override void OnMouseMove(MouseEventArgs e) {
			MouseMoving(e);
			//MouseMoveHover(e);
			if (e.Button == MouseButtons.Left) {
				DoDrag();
			}
			base.OnMouseMove(e);
		}
		protected override void OnHandleCreated(EventArgs e) {
			base.OnHandleCreated(e);
			if (!this.DesignMode) {
				this.Headers.MaxWidth = this.Width;
				this.Items.Height = this.Height;
				this.Items.Width = this.Width;
				this.Headers.Resize();
				this.Items.Rebound();
				this.Refresh();
			}
		}
		protected override void OnMouseEnter(EventArgs e) {
			base.OnMouseEnter(e);
			this.Focus();
			this.Select();
		}
		protected override void OnMouseLeave(EventArgs e) {
			#region Header Stuff
			Header h = this.Headers.Hover;
			if (h != null) {
				h.Hover = false;
				DrawHeader(this.CreateGraphics(), h);
			}
			this.Headers.UnHover();
			this.Headers.UnDrawed();
			#endregion
			#region Item Stuff
			if (this.Items.Hover != null) {
				this.Items.Hover.Hover = false;
				this.DrawItem(this.CreateGraphics(), this.Items.GetNeighbours(this.Items.Hover));
			}
			#endregion
			base.OnMouseLeave(e);			
		}
		protected override void OnKeyUp(KeyEventArgs e) {
			base.OnKeyUp(e);
			if (e.KeyValue == 38 || e.KeyValue == 40) {
				if (e.KeyValue == 38) {
					//Up
					this.SelectPrev();
				} else {
					//down
					this.SelectNext();
				}
			}
		}
		#endregion
		#region Property
		/// <summary>
		/// Gets or sets the headers.
		/// </summary>
		/// <value>The headers.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public HeaderCollection Headers {
			get {
				if (_headers == null) {
					_headers = new HeaderCollection();
				}
				return _headers;
			}
			set { _headers = value; }
		}
		/// <summary>
		/// Gets or sets the items.
		/// </summary>
		/// <value>The items.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public ListCollection Items {
			get {
				if (_items == null) {
					_items = new ListCollection();
				}
				return _items;
			}
			set { _items = value; }
		}
		/// <summary>
		/// Gets or sets the drag provider.
		/// </summary>
		/// <value>The drag provider.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public ListDrag DragProvider {
			get { return _dragProvider; }
			set { _dragProvider = value; }
		}

		/// <summary>
		/// Gets or sets a value indicating whether shows hover.
		/// </summary>
		/// <value><c>true</c> if shows hover effect; otherwise, <c>false</c>.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public bool ShowHover {
			get { return _showHover; }
			set { _showHover = value; }
		}
		#endregion
		#region Receive Events
		private void Library_Update(object sender, EventArgs e) {
			if (!this.InvokeRequired) {
				this.Items.Clear();
				if (Config.Library.Active != null) {
					for (int i = 0; i < Config.Library.Active.Count; i++) {
						this.Items.Add(new ListItem(Config.Library.Active[i]));
					}
					/*foreach (AudioPlayer.Plugin.Storage.ISong song in Config.Library.Active) {
						this.Items.Add(new ListItem(song));
					}*/
					this.Items.Height = this.Height;
					this.Items.Rebound();
					this.Items.SetVisibility(true);
				}
				this.Refresh();
			} else {
				this.Invoke(new InvLibraryScan(Library_Update), sender, e);
			}
		}
		private void DragProvider_Close(object sender, EventArgs e) {
			_dragProvider.Dispose();
			_dragProvider = null;
		}
		private void PlayControl_Starting(object sender, EventArgs e) {
			if (Config.Plugins.HasPlayControl) {
				if (Config.Plugins.PlayControl.Active != null) {
					ListItem item = this.Find(Config.Plugins.PlayControl.Active);
					if (item != null) {
						this.ItemClick(item, false);
					}
				}
			}
		}
		#endregion
	}
}
